package xyz.perkd.util;

import org.apache.fontbox.ttf.TTFParser;
import org.apache.fontbox.ttf.TrueTypeCollection;
import org.apache.fontbox.ttf.TrueTypeFont;
import org.apache.fontbox.util.autodetect.FontFileFinder;
import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.apache.pdfbox.util.Matrix;
import java.awt.geom.Rectangle2D;
import org.apache.pdfbox.text.PDFTextStripperByArea;
import org.apache.pdfbox.text.TextPosition;
import java.util.List;

import java.io.*;
import java.net.URI;

public class PdfUtil {

    private static final String DEFAULT_TTF_FILENAME = "simsun.ttf";
    private static final String DEFAULT_TTC_FILENAME = "simsun.ttc";
    private static final String DEFAULT_FONT_NAME = "SimSun";
    private static final TrueTypeFont DEFAULT_FONT;

    static {
        DEFAULT_FONT = loadSystemFont();
    }


    /**
     * 加载系统字体,提供默认字体
     *
     * @return
     */
    private synchronized static TrueTypeFont loadSystemFont() {
        //load 操作系统的默认字体. 宋体
        FontFileFinder fontFileFinder = new FontFileFinder();
        for (URI uri : fontFileFinder.find()) {
            try {
                final String filePath = uri.getPath();
                if (filePath.endsWith(DEFAULT_TTF_FILENAME)) {
                    return new TTFParser(false).parse(new RandomAccessReadBufferedFile(new File(filePath)));
                } else if (filePath.endsWith(DEFAULT_TTC_FILENAME)) {
                    TrueTypeCollection trueTypeCollection = new TrueTypeCollection(new FileInputStream(filePath));
                    final TrueTypeFont font = trueTypeCollection.getFontByName(DEFAULT_FONT_NAME);
                    //复制完之后关闭ttc
                    trueTypeCollection.close();
                    return font;
                }
            } catch (Exception e) {
                throw new RuntimeException("加载操作系统字体失败", e);
            }
        }

        return null;
    }

    public static boolean addPictureWaterMarker(PDDocument document, PDPage page) {
        try {
            addPictureToPage(document, page);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean addTextWaterMarker(PDDocument document, PDPage page, PdfWatermarkProperties properties) {
        try {
            addTextToDocument(document, page, properties);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 处理PDDocument,添加文本水印
     *
     * @param document
     * @param props
     * @throws IOException
     */
    public static void addTextToDocument(PDDocument document, PDPage page, PdfWatermarkProperties props) throws IOException {
        document.setAllSecurityToBeRemoved(true);
        // 遍历PDF文件，在每一页加上水印
            PDPageContentStream stream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true);

            // 加载水印字体
            if (DEFAULT_FONT == null) {
                throw new RuntimeException(String.format("未提供默认字体.请安装字体文件%s或%s", DEFAULT_TTF_FILENAME, DEFAULT_TTC_FILENAME));
            }

            PDFont font;
            if (props.getFontFile() != null) {
                font = PDType0Font.load(document, props.getFontFile());
            } else {
                //当TrueTypeFont为字体集合时, embedSubSet 需要设置为true, 嵌入其子集
                font = PDType0Font.load(document, DEFAULT_FONT, true);
            }

            PDExtendedGraphicsState r = new PDExtendedGraphicsState();

            // 设置透明度
            r.setNonStrokingAlphaConstant(props.getTransparency());
            r.setAlphaSourceFlag(true);
            stream.setGraphicsStateParameters(r);

            // 设置水印字体颜色
            final float[] color = props.getColor();
            stream.setNonStrokingColor(color[0], color[1], color[2]);
            stream.beginText();
            stream.setFont(font, props.getFontSize());

            // 获取PDF页面大小
            float pageHeight = page.getMediaBox().getHeight();
            float pageWidth = page.getMediaBox().getWidth();

            // 根据纸张大小添加水印，30度倾斜
//            for (int h = props.getY(); h < pageHeight; h = h + props.getHeight()) {
//                for (int w = props.getX(); w < pageWidth; w = w + props.getWidth()) {
                    stream.setTextMatrix(Matrix.getRotateInstance(props.getRotate(), props.getX(), props.getY()));
                    stream.showText(props.getContent());
//                }
//            }

            // 结束渲染，关闭流
            stream.endText();
            stream.restoreGraphicsState();
            stream.close();
    }

    /**
     * 处理PDDocument,添加文本水印
     *
     * @param document
     * @param page
     * @throws IOException
     */
    public static void addPictureToPage(PDDocument document, PDPage page) throws IOException {
        document.setAllSecurityToBeRemoved(true);
        // 遍历PDF文件，在每一页加上水印
        PDPageContentStream stream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true);

        PDExtendedGraphicsState r = new PDExtendedGraphicsState();

        // 设置透明度
        r.setNonStrokingAlphaConstant(0.3F);
        r.setAlphaSourceFlag(true);
        stream.setGraphicsStateParameters(r);

        String workDir = System.getProperty("user.dir");
        PDImageXObject pdImageXObject = PDImageXObject.createFromFile(workDir + "/watermaker.jpg", document);

        stream.drawImage(pdImageXObject, 480, 75, 100, 40);

        stream.close();
    }

    public static String getTextByArea(PDDocument document, PDPage page, Rectangle2D rect) {
        try {
            PDFTextStripperByArea stripper = new PDFTextStripperByArea();
            // 设置要提取文本的矩形区域，例如页面上的一个矩形区域
            stripper.addRegion("myRegion", rect); // x, y, width, height

            stripper.extractRegions(page);
            String text = stripper.getTextForRegion("myRegion");
            return text;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}
